#include "bsp.h"

#include "SW_I2C/sw_i2c.h"	
#include "SW_I2C/sw_i2c_ex.h"

#define CST816_RST_1() 	CST816_RST_PORT->BSRR = CST816_RST_PIN;
#define CST816_RST_0() 	CST816_RST_PORT->BSRR = CST816_RST_PIN << 16;

/* 定义IO = 1和 0的代码  */
#define I2C_SDA_1()		CST816_SDA_PORT->BSRR = CST816_SDA_PIN
#define I2C_SDA_0()		CST816_SDA_PORT->BSRR = CST816_SDA_PIN << 16;

#define I2C_SCL_1()		CST816_SCL_PORT->BSRR = CST816_SCL_PIN
#define I2C_SCL_0()		CST816_SCL_PORT->BSRR = CST816_SCL_PIN << 16;

#define I2C_SDA_READ()  ((CST816_SDA_PORT->IDR & CST816_SDA_PIN) != 0)	/* 读SDA口线状态 */
// #define I2C_SCL_READ()  ((CST816_SCL_PORT->IDR & CST816_SCL_PIN) != 0)	/* 读SCL口线状态 */

#define I2C_WR	0		/* 写控制bit */
#define I2C_RD	1		/* 读控制bit */

// I2C总线时序接口函数
static void I2C_SDA_LOW(void);
static void I2C_SDA_HIGH(void);
static void I2C_SCL_LOW(void);
static void I2C_SCL_HIGH(void);
static uint8_t I2C_SDA_READ_LEVEL(void);
static void I2C_SDA_SET_INPUT(void);
static void I2C_SDA_SET_OUTPUT(void);
static void I2C_Delay(uint32_t us);

/* Private variables ---------------------------------------------------------*/
// 定义i2c驱动对象
static sw_i2c_dev_t i2c_cst816_dev;

static void cst816_gpio_config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    /* 打开GPIO时钟 */
    RCC_AHB1PeriphClockCmd(RCC_CST816_PORT, ENABLE);

    // SCL SDA
    /* 配置为开漏输出 */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;		/* 设为输出口 */
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

    GPIO_InitStructure.GPIO_Pin = CST816_SDA_PIN;
    GPIO_Init(CST816_SDA_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = CST816_SCL_PIN;
    GPIO_Init(CST816_SCL_PORT, &GPIO_InitStructure);

    // RST
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;		/* 设为输出口 */
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

    GPIO_InitStructure.GPIO_Pin = CST816_RST_PIN;
    GPIO_Init(CST816_RST_PORT, &GPIO_InitStructure);

    /*释放SCL和SDA*/
    I2C_SDA_1();
    I2C_SCL_1();

}


static void cst816_i2c_config(void)
{
    i2c_cst816_dev.name               = "i2c_cst816";
    i2c_cst816_dev.speed              = 2; /*! speed:105Hz */
    i2c_cst816_dev.delay_us           = I2C_Delay;
    i2c_cst816_dev.ops.sda_low        = I2C_SDA_LOW;
    i2c_cst816_dev.ops.sda_high       = I2C_SDA_HIGH;
    i2c_cst816_dev.ops.scl_low        = I2C_SCL_LOW;
    i2c_cst816_dev.ops.scl_high       = I2C_SCL_HIGH;
    i2c_cst816_dev.ops.sda_read_level = I2C_SDA_READ_LEVEL;
    i2c_cst816_dev.ops.sda_set_input  = I2C_SDA_SET_INPUT;
    i2c_cst816_dev.ops.sda_set_output = I2C_SDA_SET_OUTPUT;
    sw_i2c_init(&i2c_cst816_dev); 

}

static void cst816_write_reg(uint8_t reg_addr, uint8_t data)
{
    sw_i2c_ex_write_byte(&i2c_cst816_dev, CST816_I2C_ADDR, reg_addr, data);
}

static uint8_t cst816_read_reg(uint8_t reg_addr)
{
    uint8_t data = 0;
    sw_i2c_ex_read_byte(&i2c_cst816_dev, CST816_I2C_ADDR, reg_addr, &data);
    return data;
}


void bsp_cst816_init(void)
{
    // 引脚初始化
    cst816_gpio_config();
    // 软件i2c初始化
    cst816_i2c_config();
    // 唤醒
    bsp_cst816_wakeup();
    // 配置自动休眠时间
    bsp_cst816_set_AutoSleepTime(5);


}

// 函数：bsp_touch_cst816_reset
// 功能：重置CST816触摸屏
void bsp_cst816_reset(void)
{
    CST816_RST_0();
    HAL_Delay_ms(10);
    CST816_RST_1();
    HAL_Delay_ms(100);
}

#define TOUCH_OFFSET_Y 15
void bsp_cst816_get_xy_axis(uint32_t *x_pos, uint32_t *y_pos)
{
    uint8_t data[4] = {0};
    sw_i2c_ex_read_bytes(&i2c_cst816_dev, CST816_I2C_ADDR, XposH, data, 4);
    *x_pos = ((data[0] & 0x0F) << 8) | data[1];
    *y_pos = ((data[2] & 0x0F) << 8) | data[3] + TOUCH_OFFSET_Y;
}

// 函数用于获取CST816触摸芯片的ID
uint8_t bsp_cst816_get_chipid(void)
{    
    return cst816_read_reg(ChipID);
}

// 获取触摸屏上的手指数量
uint8_t bsp_cst816_get_fingernum(void)
{
    return cst816_read_reg(FingerNum);
}

/*
*********************************************************************************************************
*	函 数 名: CST816_Config_AutoSleepTime
*	功能说明: 规定time内无触摸，自动进入低功耗模式
*	形    参：time：时间(s)
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_cst816_set_AutoSleepTime(uint8_t time)
{
    cst816_write_reg(AutoSleepTime, time);
}

/*
*********************************************************************************************************
*	函 数 名: CST816_Config_MotionMask
*	功能说明: 使能连续动作（连续左右滑动，连续上下滑动，双击）
*	形    参：mode：模式(5种)
*	返 回 值: 无
*	注    意：使能连续动作会增加响应时间
*********************************************************************************************************
*/
void bsp_cst816_set_MotionMask(uint8_t mode)
{
    cst816_write_reg(MotionMask, mode);
}

/*
*********************************************************************************************************
*	函 数 名: CST816_Config_MotionSlAngle
*	功能说明: 手势检测滑动分区角度控制。Angle=tan(c)*10 c为以x轴正方向为基准的角度。
*	形    参：x_right_y_up_angle：角度值
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_cst816_set_MotionSlAngle(uint8_t x_right_y_up_angle)
{
    cst816_write_reg(MotionSlAngle, x_right_y_up_angle);
}

/*
*********************************************************************************************************
*	函 数 名: CST816_Config_NorScanPer
*	功能说明: 正常快速检测周期配置函数。
*						此值会影响到LpAutoWakeTime和AutoSleepTime。 
*						单位10ms，可选值：1～30。默认值为1。
*	形    参：Period：周期值
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_cst816_set_NorScanPer(uint8_t period)
{
    if(period >= 30)
		period = 30;
    cst816_write_reg(NorScanPer, period);
}

/*
*********************************************************************************************************
*	函 数 名: CST816_Config_IrqPluseWidth
*	功能说明: 中断低脉冲输出宽度配置函数
*	形    参：Period：周期值
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_cst816_set_IrqPluseWidth(uint8_t width)
{
	if(width >= 200)
		width = 200;
    cst816_write_reg(IrqPluseWidth, width);
}

/*
*********************************************************************************************************
*	函 数 名: CST816_Config_NorScanPer
*	功能说明: 低功耗扫描唤醒门限配置函数。越小越灵敏。默认值48
*	形    参：TH：门限值
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_cst816_set_LpScanTH(uint8_t th)
{
    cst816_write_reg(LpScanTH, th);
}


/*
*********************************************************************************************************
*	函 数 名: CST816_Sleep
*	功能说明: 进入睡眠，无触摸唤醒功能
*	形    参：无
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_cst816_sleep(void)
{
    // 向CST816触摸屏写入睡眠模式寄存器
    cst816_write_reg(SleepMode, 0x03);
}

/*
*********************************************************************************************************
*	函 数 名: CST816_Wakeup
*	功能说明: 唤醒
*	形    参：无
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_cst816_wakeup(void)
{
    // 调用bsp_cst816_reset函数，重置CST816触摸屏
    bsp_cst816_reset();
}



/***********************************************************************/


static void I2C_SDA_LOW(void)
{
    I2C_SDA_0();
}

static void I2C_SDA_HIGH(void)
{
    I2C_SDA_1();
}

static void I2C_SCL_LOW(void)
{
    I2C_SCL_0();
}

static void I2C_SCL_HIGH(void)
{
    I2C_SCL_1();
}

static uint8_t I2C_SDA_READ_LEVEL(void)
{
    return I2C_SDA_READ();
}

static void I2C_SDA_SET_INPUT(void)
{
    I2C_SDA_1(); // 释放SDA引脚

}

static void I2C_SDA_SET_OUTPUT(void)
{

}

static void I2C_Delay(uint32_t us)
{
    HAL_Delay_us(us);
}





